package main

import (
	"context"
	consulregistry "github.com/go-kratos/kratos/contrib/registry/consul/v2"
	"github.com/go-kratos/kratos/v2/middleware/recovery"
	"github.com/go-kratos/kratos/v2/middleware/tracing"
	"github.com/go-kratos/kratos/v2/transport/grpc"
	"github.com/go-kratos/kratos/v2/transport/http"
	consul "github.com/hashicorp/consul/api"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/sdk/resource"
	tracesdk "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
	v1 "kratos-demo-layout/api/helloworld/v1"
	"log"
	"time"
)

func main() {
	cfg := &consul.Config{
		Address: "192.168.94.103:8500",
	}

	client, err := consul.NewClient(cfg)
	if err != nil {
		log.Fatal(err)
	}
	r := consulregistry.New(client)

	endPoint := "discovery:///kratos-demo-layout"

	err = initTracer("http://192.168.94.103:14268/api/traces")
	if err != nil {
		panic(err)
	}

	// new http client
	hConn, err := http.NewClient(
		context.Background(),
		http.WithMiddleware(
			recovery.Recovery(),
			tracing.Client(),
		),
		http.WithEndpoint(endPoint),
		http.WithDiscovery(r),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer hConn.Close()
	hClient := v1.NewGreeterHTTPClient(hConn)

	// new grpc client
	conn, err := grpc.DialInsecure(
		context.Background(),
		grpc.WithEndpoint(endPoint),
		grpc.WithDiscovery(r),
		grpc.WithMiddleware(
			tracing.Client(),
		),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	gClient := v1.NewGreeterClient(conn)
	for {
		time.Sleep(time.Second)
		callGRPC(gClient)
		callHTTP(hClient)
	}
}

func callGRPC(client v1.GreeterClient) {
	reply, err := client.SayHello(context.Background(), &v1.HelloRequest{Name: "grpc:kratos"})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[grpc] SayHello %s\n", reply.Message)
}

func callHTTP(client v1.GreeterHTTPClient) {
	reply, err := client.SayHello(context.Background(), &v1.HelloRequest{Name: "http:kratos"})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("[http] SayHello %s\n", reply.Message)
}

// 设置全局trace
func initTracer(url string) error {
	// 创建 Jaeger exporter
	exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
	if err != nil {
		return err
	}
	tp := tracesdk.NewTracerProvider(
		// 将基于父span的采样率设置为100%
		tracesdk.WithSampler(tracesdk.ParentBased(tracesdk.TraceIDRatioBased(1.0))),
		// 始终确保再生成中批量处理
		tracesdk.WithBatcher(exp),
		// 在资源中记录有关此应用程序的信息
		tracesdk.WithResource(resource.NewSchemaless(
			semconv.ServiceNameKey.String("kratos-demo-layout"),
			attribute.String("exporter", "jaeger"),
			attribute.Float64("float", 312.23),
		)),
	)
	otel.SetTracerProvider(tp)
	return nil
}
